Дата публикации: 04.07.2009
Обновлено: 19.01.2018

Работа с типами BOOLEAN и GUID в Firebird и InterBase

Суть проблемы

  • Тип GUID на текущий момент не поддерживается ни одним сервером Firebird и InterBase, но нередко используется различными клиентами (к примеру, в ADO Entity Framework).
  • Тип Boolean поддерживается в InterBase начиная с 7-й версии и в Firebird начиная с 3-й версии.

В IBProvider поддержка типов Guid и Boolean была реализована на уровне драйвера, и теперь вы можете свободно использовать эти типы в своих приложениях независимо от версии сервера Firebird и InterBase.

Данные хранятся в типах, которые поддерживаются сервером. IBProvider просматривает домены данных и если обнаруживается домен, подходящий по маске, он выставляет колонке соответствующий тип Boolean или Guid.

Домены должны удовлетворять следующим условиям:

  • для типа BOOLEAN домен базируется на типе SMALLINT.
  • для типа GUID домен базируется на типе CHAR(16) с кодовой страницей OCTETS.

Свойства для включения эмуляции типов

Для того чтобы указать провайдеру какие данные следует интерпретировать как Boolean или Guid, в IBProvider добавлены два новых свойства инициализации: user_type_boolean, user_type_guid. В них определяется маска домена, который представляет эмулируемый тип. В маске поддерживаются символы «*» и «?». Маска чувствительна к регистру.

При несоблюдении этих условий, провайдер игнорирует имя домена и не пытается выполнять подмену типа.

Эмуляция работает для:

  • Колонок с простым типом;
  • Колонок с массивами;
  • OUT-параметров с простым типом;
  • OUT-параметров с массивами;
  • IN-параметров с массивами.

Ограничения эмуляции типов

Из-за ограничений ISC API (IB/FB), при использовании простых типов для входящих параметров команд, необходимо явно указывать тип параметра. Для колонок с массивами поддерживается автоматическое формирование описания параметра.

Эмуляция типов в метаданных

Эмуляция типов распространяется и на схемы метаданных. Провайдер обеспечивает согласованность типов, которые читаются при выполнении запросов и типов, которые отображаются в схемах COLUMNS, PROCEDURE_PARAMETERS, PROCEDURE_COLUMNS.

Рабочий пример

Для демонстрации работы нам понадобится:

Для начала создадим тестовую таблицу и домены, в которых будут храниться данные эмулируемых типов.

CREATE DOMAIN D_BOOL_D1 AS SMALLINT;
CREATE DOMAIN D_GUID AS CHAR(16) CHARACTER SET OCTETS;

CREATE TABLE TYPE_EMULATOR (
    IDENTITY D_GUID,
      RESIDENT D_BOOL_D1 NOT NULL,
      FULLNAME VARCHAR(100));

Для того чтобы провайдер включил эмуляцию типов, необходимо в строке подключения задать маску, по которой будут отбираться домены:

user_type_boolean= D_BOOL_*;user_type_guid= D_GUID;

Далее пример кода на Visual C#, демонстрирующего использование эмулятора типов:

[Test]
public void ComlexEmulatorTest()
{
    // retrive standard connection string parameters from config
    OleDbConnectionStringBuilder sb = ConnectionProvider.GetConnectionStringBuilderFromUDL();
    // add 2 masks for domains
    sb.Add("user_type_boolean", "D_BOOL*");
    sb.Add("user_type_guid", "D_GUID*");
    // disable resourse pooling because DROP operators are used
    sb.OleDbServices = OleDbServicesValues.EnableAll & ~OleDbServicesValues.ResourcePooling;

    using (OleDbConnection cn = new OleDbConnection(sb.ToString()))
    {
        cn.Open();

        // inserting...
        OleDbTransaction tran = cn.BeginTransaction(IsolationLevel.RepeatableRead);
        OleDbCommand cmd = new OleDbCommand(
        "insert into type_emulator (identity, resident, fullname) values (?,?,?) ", cn, tran);

        Guid guid = Guid.NewGuid();
        cmd.Parameters.Add("identity", OleDbType.Guid).Value = guid;
        cmd.Parameters.Add("resident", OleDbType.Boolean).Value = true;
        cmd.Parameters.AddWithValue("fullname", "Resident of Russian Federation");

        Assert.AreEqual(cmd.ExecuteNonQuery(), 1);
        tran.Commit();

        // selecting and validating
        tran = cn.BeginTransaction(IsolationLevel.RepeatableRead);
        cmd = new OleDbCommand("select * from type_emulator", cn, tran);

        using (OleDbDataReader rdr = cmd.ExecuteReader())
        {
            if (rdr.Read())
            {
                Console.WriteLine("Identity: {0} [type: {1}]", rdr["identity"], rdr["identity"].GetType().Name);
                Console.WriteLine("Resident: {0} [type: {1}]", rdr["resident"], rdr["resident"].GetType().Name);
                Console.WriteLine("Fullname: {0} [type: {1}]", rdr["fullname"], rdr["fullname"].GetType().Name);

                // check values
                Assert.AreEqual(guid, rdr["identity"]);
                Assert.AreEqual(rdr["resident"], true);
            }
            else
                Assert.Fail("Row was not inserted");
        }

        tran.Commit();
    } // Dispose cn.close
}

Если свойства user_type_boolean и user_type_guid установлены правильно и версия IBProvider Professional не ниже 3.0.0.7412, в консоли будет отображен следующий текст:

identity: 6ef41c55-03ff-4941-9382-290813ad46c2 [type: Guid]
Resident: True [type: Boolean]
Fullname: Resident of Russian Federation [type: String]

Обратите внимание на то, что значения и типы в ADO .Net определены правильно в соответствии с заданными масками для доменов. В случае если маска домена не задана или используется другой провайдер после выполнения данного примера на экране отобразится текст:

identity: System.Byte[] [type: Byte[]]
Resident: 1 [type: Int16]
Fullname: Resident of Russian Federation [type: String]

То есть вместо типов Guid и Boolean будут отображаться стандартные типы.

Исходные тексты примеров для ADO .Net можно скачать здесь: Firebird ADO .Net Samples

Автор: Andrew A. Merkulov  

Дата публикации: 04.07.2009. Права на материал принадлежат: IBProvider. При перепечатке ссылка на сайт https://www.ibprovider.com/rus обязательна.